<!DOCTYPE html>
<html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<head>
<meta content='IE=EmulateIE7' http-equiv='X-UA-Compatible'/>
<meta content='width=1100' name='viewport'/>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
<script type="text/javascript">(function() { var b=window,f="chrome",g="tick",k="jstiming";(function(){function d(a){this.t={};this.tick=function(a,d,c){var e=void 0!=c?c:(new Date).getTime();this.t[a]=[e,d];if(void 0==c)try{b.console.timeStamp("CSI/"+a)}catch(h){}};this[g]("start",null,a)}var a;b.performance&&(a=b.performance.timing);var n=a?new d(a.responseStart):new d;b.jstiming={Timer:d,load:n};if(a){var c=a.navigationStart,h=a.responseStart;0<c&&h>=c&&(b[k].srt=h-c)}if(a){var e=b[k].load;0<c&&h>=c&&(e[g]("_wtsrt",void 0,c),e[g]("wtsrt_","_wtsrt",h),e[g]("tbsd_","wtsrt_"))}try{a=null,
b[f]&&b[f].csi&&(a=Math.floor(b[f].csi().pageT),e&&0<c&&(e[g]("_tbnd",void 0,b[f].csi().startE),e[g]("tbnd_","_tbnd",c))),null==a&&b.gtbExternal&&(a=b.gtbExternal.pageT()),null==a&&b.external&&(a=b.external.pageT,e&&0<c&&(e[g]("_tbnd",void 0,b.external.startE),e[g]("tbnd_","_tbnd",c))),a&&(b[k].pt=a)}catch(p){}})();b.tickAboveFold=function(d){var a=0;if(d.offsetParent){do a+=d.offsetTop;while(d=d.offsetParent)}d=a;750>=d&&b[k].load[g]("aft")};var l=!1;function m(){l||(l=!0,b[k].load[g]("firstScrollTime"))}b.addEventListener?b.addEventListener("scroll",m,!1):b.attachEvent("onscroll",m);
 })();</script>
<meta content='blogger' name='generator'/>
<link href='http://www.javaadvent.com/favicon.ico' rel='icon' type='image/x-icon'/>
<link href='http://www.javaadvent.com/2013/12/anatomy-of-java-decompiler.html' rel='canonical'/>
<link rel="alternate" type="application/atom+xml" title="Java Advent Calendar - Atom" href="http://www.javaadvent.com/feeds/posts/default" />
<link rel="alternate" type="application/rss+xml" title="Java Advent Calendar - RSS" href="http://www.javaadvent.com/feeds/posts/default?alt=rss" />
<link rel="service.post" type="application/atom+xml" title="Java Advent Calendar - Atom" href="http://www.blogger.com/feeds/2481158163384033132/posts/default" />

<link rel="alternate" type="application/atom+xml" title="Java Advent Calendar - Atom" href="http://www.javaadvent.com/feeds/8102289133489793686/comments/default" />
<!--[if IE]><script type="text/javascript" src="https://www.blogger.com/static/v1/jsbin/1969951888-ieretrofit.js"></script>
<![endif]-->
<link href='https://upload.wikimedia.org/wikipedia/commons/2/26/Simplified_Control_Flowgraphs.jpg' rel='image_src'/>
<!--[if IE]> <script> (function() { var html5 = ("abbr,article,aside,audio,canvas,datalist,details," + "figure,footer,header,hgroup,mark,menu,meter,nav,output," + "progress,section,time,video").split(','); for (var i = 0; i < html5.length; i++) { document.createElement(html5[i]); } try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {} })(); </script> <![endif]-->
<title>Java Advent Calendar: Anatomy of a Java Decompiler</title>
<link href='//hype-free.googlecode.com/svn/trunk/google-code-prettify/prettify.css' rel='stylesheet' type='text/css'/>
<link type='text/css' rel='stylesheet' href='https://www.blogger.com/static/v1/widgets/3681447274-widget_css_2_bundle.css' />
<link type='text/css' rel='stylesheet' href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=2481158163384033132&zx=3be10e8f-8131-4f15-8a77-de21d1b75fd9' />
<style id='page-skin-1' type='text/css'><!--
/*
-----------------------------------------------
Blogger Template Style
Name:     Simple
Designer: Josh Peterson
URL:      www.noaesthetic.com
----------------------------------------------- */
/* Variable definitions
====================
<Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/>
<Group description="Page Text" selector="body">
<Variable name="body.font" description="Font" type="font"
default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/>
<Variable name="body.text.color" description="Text Color" type="color" default="#222222"/>
</Group>
<Group description="Backgrounds" selector=".body-fauxcolumns-outer">
<Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/>
<Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/>
<Variable name="header.background.color" description="Header Background" type="color" default="transparent"/>
</Group>
<Group description="Links" selector=".main-outer">
<Variable name="link.color" description="Link Color" type="color" default="#2288bb"/>
<Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/>
<Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/>
</Group>
<Group description="Blog Title" selector=".header h1">
<Variable name="header.font" description="Font" type="font"
default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/>
<Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" />
</Group>
<Group description="Blog Description" selector=".header .description">
<Variable name="description.text.color" description="Description Color" type="color"
default="#777777" />
</Group>
<Group description="Tabs Text" selector=".tabs-inner .widget li a">
<Variable name="tabs.font" description="Font" type="font"
default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/>
<Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/>
<Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/>
</Group>
<Group description="Tabs Background" selector=".tabs-outer .PageList">
<Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/>
<Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/>
</Group>
<Group description="Post Title" selector="h3.post-title, .comments h4">
<Variable name="post.title.font" description="Font" type="font"
default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/>
</Group>
<Group description="Date Header" selector=".date-header">
<Variable name="date.header.color" description="Text Color" type="color"
default="#222222"/>
<Variable name="date.header.background.color" description="Background Color" type="color"
default="transparent"/>
</Group>
<Group description="Post Footer" selector=".post-footer">
<Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/>
<Variable name="post.footer.background.color" description="Background Color" type="color"
default="#f9f9f9"/>
<Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/>
</Group>
<Group description="Gadgets" selector="h2">
<Variable name="widget.title.font" description="Title Font" type="font"
default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/>
<Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/>
<Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/>
</Group>
<Group description="Images" selector=".main-inner">
<Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/>
<Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/>
<Variable name="image.text.color" description="Caption Text Color" type="color" default="#222222"/>
</Group>
<Group description="Accents" selector=".content-inner">
<Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/>
<Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="#eeeddd"/>
</Group>
<Variable name="body.background" description="Body Background" type="background"
color="#514831" default="$(color) none repeat scroll top left"/>
<Variable name="body.background.override" description="Body Background Override" type="string" default=""/>
<Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url"
default="url(//www.blogblog.com/1kt/simple/gradients_light.png)"/>
<Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url"
default="url(//www.blogblog.com/1kt/simple/body_gradient_tile_light.png)"/>
<Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/>
<Variable name="content.padding" description="Content Padding" type="length" default="10px"/>
<Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px"/>
<Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px"/>
<Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px"/>
<Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px"/>
<Variable name="main.border.width" description="Main Border Width" type="length" default="0"/>
<Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/>
<Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px"/>
<Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px"/>
<Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px"/>
<Variable name="header.padding" description="Header Padding" type="length" default="30px"/>
<Variable name="header.border.size" description="Header Border Size" type="length" default="1px"/>
<Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="0"/>
<Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0"/>
<Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/>
<Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" />
<Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" />
<Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url"
default="url(//www.blogblog.com/1kt/simple/gradients_light.png)"/>
<Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px"/>
<Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px"/>
<Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/>
<Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/>
<Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/>
<Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px"/>
<Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px"/>
<Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px"/>
<Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/>
<Variable name="page.width" description="Page Width" type="string" default="auto"/>
<Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px"/>
<Variable name="main.padding" description="Main Padding" type="length" default="15px"/>
<Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px"/>
<Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px"/>
<Variable name="paging.background"
color="#fcffee"
description="Background of blog paging area" type="background"
default="transparent none no-repeat scroll top center"/>
<Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0"/>
<Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string"
default="transparent none repeat scroll top left"/>
<Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/>
<Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" />
<Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/>
<Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/>
*/
/* Content
----------------------------------------------- */
body {
font: normal normal 16px Verdana, Geneva, sans-serif;
color: #222222;
background: #513831 url(//themes.googleusercontent.com/image?id=1KH22PlFqsiVYxboQNAoJjYmRbw5M4REHmdJbHT5M2x9zVMGrCqwSjZvaQW_A10KPc6Il) repeat scroll top center /* Credit: luoman (http://www.istockphoto.com/googleimages.php?id=11394138&amp;platform=blogger) */;
padding: 0 40px 40px 40px;
}
html body .region-inner {
min-width: 0;
max-width: 100%;
width: auto;
}
a:link {
text-decoration:none;
color: #997f00;
}
a:visited {
text-decoration:none;
color: #888888;
}
a:hover {
text-decoration:underline;
color: #ff9800;
}
.body-fauxcolumn-outer .fauxcolumn-inner {
background: transparent none repeat scroll top left;
_background-image: none;
}
.body-fauxcolumn-outer .cap-top {
position: absolute;
z-index: 1;
height: 400px;
width: 100%;
background: #513831 url(//themes.googleusercontent.com/image?id=1KH22PlFqsiVYxboQNAoJjYmRbw5M4REHmdJbHT5M2x9zVMGrCqwSjZvaQW_A10KPc6Il) repeat scroll top center /* Credit: luoman (http://www.istockphoto.com/googleimages.php?id=11394138&amp;platform=blogger) */;
}
.body-fauxcolumn-outer .cap-top .cap-left {
width: 100%;
background: transparent none repeat-x scroll top left;
_background-image: none;
}
.content-outer {
-moz-box-shadow: 0 0 40px rgba(0, 0, 0, .15);
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .15);
-goog-ms-box-shadow: 0 0 10px #333333;
box-shadow: 0 0 40px rgba(0, 0, 0, .15);
margin-bottom: 1px;
}
.content-inner {
padding: 10px 10px;
}
.content-inner {
background-color: #fcffee;
}
/* Header
----------------------------------------------- */
.header-outer {
background: #afcc66 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -400px;
_background-image: none;
}
.Header h1 {
font: normal normal 48px Georgia, Utopia, 'Palatino Linotype', Palatino, serif;
color: #ffffff;
text-shadow: 1px 2px 3px rgba(0, 0, 0, .2);
}
.Header h1 a {
color: #ffffff;
}
.Header .description {
font-size: 140%;
color: #ffffff;
}
.header-inner .Header .titlewrapper {
padding: 22px 30px;
}
.header-inner .Header .descriptionwrapper {
padding: 0 30px;
}
/* Tabs
----------------------------------------------- */
.tabs-inner .section:first-child {
border-top: 0 solid #eeeddd;
}
.tabs-inner .section:first-child ul {
margin-top: -0;
border-top: 0 solid #eeeddd;
border-left: 0 solid #eeeddd;
border-right: 0 solid #eeeddd;
}
.tabs-inner .widget ul {
background: #fcffee none repeat-x scroll 0 -800px;
_background-image: none;
border-bottom: 1px solid #eeeddd;
margin-top: 0;
margin-left: -30px;
margin-right: -30px;
}
.tabs-inner .widget li a {
display: inline-block;
padding: .6em 1em;
font: normal normal 16px Georgia, Utopia, 'Palatino Linotype', Palatino, serif;
color: #999977;
border-left: 1px solid #fcffee;
border-right: 1px solid #eeeddd;
}
.tabs-inner .widget li:first-child a {
border-left: none;
}
.tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover {
color: #000000;
background-color: #fcffee;
text-decoration: none;
}
/* Columns
----------------------------------------------- */
.main-outer {
border-top: 0 solid #eeeddd;
}
.fauxcolumn-left-outer .fauxcolumn-inner {
border-right: 1px solid #eeeddd;
}
.fauxcolumn-right-outer .fauxcolumn-inner {
border-left: 1px solid #eeeddd;
}
/* Headings
----------------------------------------------- */
h2 {
margin: 0 0 1em 0;
font: normal bold 12px Georgia, Utopia, 'Palatino Linotype', Palatino, serif;
color: #000000;
}
/* Widgets
----------------------------------------------- */
.widget .zippy {
color: #999999;
text-shadow: 2px 2px 1px rgba(0, 0, 0, .1);
}
.widget .popular-posts ul {
list-style: none;
}
/* Posts
----------------------------------------------- */
.date-header span {
background-color: transparent;
color: #222222;
padding: inherit;
letter-spacing: inherit;
margin: inherit;
}
.main-inner {
padding-top: 30px;
padding-bottom: 30px;
}
.main-inner .column-center-inner {
padding: 0 15px;
}
.main-inner .column-center-inner .section {
margin: 0 15px;
}
.post {
margin: 0 0 25px 0;
}
h3.post-title, .comments h4 {
font: normal normal 24px Georgia, Utopia, 'Palatino Linotype', Palatino, serif;
margin: .75em 0 0;
}
.post-body {
font-size: 110%;
line-height: 1.4;
position: relative;
}
.post-body img, .post-body .tr-caption-container, .Profile img, .Image img,
.BlogList .item-thumbnail img {
padding: 2px;
background: #ffffff;
border: 1px solid #eeeeee;
-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
}
.post-body img, .post-body .tr-caption-container {
padding: 5px;
}
.post-body .tr-caption-container {
color: #222222;
}
.post-body .tr-caption-container img {
padding: 0;
background: transparent;
border: none;
-moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1);
-webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1);
box-shadow: 0 0 0 rgba(0, 0, 0, .1);
}
.post-header {
margin: 0 0 1.5em;
line-height: 1.6;
font-size: 90%;
}
.post-footer {
margin: 20px -2px 0;
padding: 5px 10px;
color: #5e6655;
background-color: #eaeedd;
border-bottom: 1px solid #eeeeee;
line-height: 1.6;
font-size: 90%;
}
#comments .comment-author {
padding-top: 1.5em;
border-top: 1px solid #eeeddd;
background-position: 0 1.5em;
}
#comments .comment-author:first-child {
padding-top: 0;
border-top: none;
}
.avatar-image-container {
margin: .2em 0 0;
}
#comments .avatar-image-container img {
border: 1px solid #eeeeee;
}
/* Comments
----------------------------------------------- */
.comments .comments-content .icon.blog-author {
background-repeat: no-repeat;
background-image: url();
}
.comments .comments-content .loadmore a {
border-top: 1px solid #999999;
border-bottom: 1px solid #999999;
}
.comments .comment-thread.inline-thread {
background-color: #eaeedd;
}
.comments .continue {
border-top: 2px solid #999999;
}
/* Accents
---------------------------------------------- */
.section-columns td.columns-cell {
border-left: 1px solid #eeeddd;
}
.blog-pager {
background: transparent none no-repeat scroll top center;
}
.blog-pager-older-link, .home-link,
.blog-pager-newer-link {
background-color: #fcffee;
padding: 5px;
}
.footer-outer {
border-top: 0 dashed #bbbbbb;
}
/* Mobile
----------------------------------------------- */
body.mobile  {
background-size: auto;
}
.mobile .body-fauxcolumn-outer {
background: transparent none repeat scroll top left;
}
.mobile .body-fauxcolumn-outer .cap-top {
background-size: 100% auto;
}
.mobile .content-outer {
-webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15);
box-shadow: 0 0 3px rgba(0, 0, 0, .15);
}
body.mobile .AdSense {
margin: 0 -40px;
}
.mobile .tabs-inner .widget ul {
margin-left: 0;
margin-right: 0;
}
.mobile .post {
margin: 0;
}
.mobile .main-inner .column-center-inner .section {
margin: 0;
}
.mobile .date-header span {
padding: 0.1em 10px;
margin: 0 -10px;
}
.mobile h3.post-title {
margin: 0;
}
.mobile .blog-pager {
background: transparent none no-repeat scroll top center;
}
.mobile .footer-outer {
border-top: none;
}
.mobile .main-inner, .mobile .footer-inner {
background-color: #fcffee;
}
.mobile-index-contents {
color: #222222;
}
.mobile-link-button {
background-color: #997f00;
}
.mobile-link-button a:link, .mobile-link-button a:visited {
color: #ffffff;
}
.mobile .tabs-inner .section:first-child {
border-top: none;
}
.mobile .tabs-inner .PageList .widget-content {
background-color: #fcffee;
color: #000000;
border-top: 1px solid #eeeddd;
border-bottom: 1px solid #eeeddd;
}
.mobile .tabs-inner .PageList .widget-content .pagelist-arrow {
border-left: 1px solid #eeeddd;
}
/* ---------------- */
pre.prettyprint {
display: block;
overflow: auto;
width: auto;
max-height: 700px;
white-space: pre;
word-wrap: normal;
padding: 10px;
}
code.prettyprint {
display: block;
overflow: auto;
width: auto;
max-height: 700px;
white-space: pre;
word-wrap: normal;
padding: 10px;
}
--></style>
<style id='template-skin-1' type='text/css'><!--
body {
min-width: 880px;
}
.content-outer, .content-fauxcolumn-outer, .region-inner {
min-width: 880px;
max-width: 880px;
_width: 880px;
}
.main-inner .columns {
padding-left: 0px;
padding-right: 0px;
}
.main-inner .fauxcolumn-center-outer {
left: 0px;
right: 0px;
/* IE6 does not respect left and right together */
_width: expression(this.parentNode.offsetWidth -
parseInt("0px") -
parseInt("0px") + 'px');
}
.main-inner .fauxcolumn-left-outer {
width: 0px;
}
.main-inner .fauxcolumn-right-outer {
width: 0px;
}
.main-inner .column-left-outer {
width: 0px;
right: 100%;
margin-left: -0px;
}
.main-inner .column-right-outer {
width: 0px;
margin-right: -0px;
}
#layout {
min-width: 0;
}
#layout .content-outer {
min-width: 0;
width: 800px;
}
#layout .region-inner {
min-width: 0;
width: auto;
}
--></style>
<style>
pre.prettyprint {
background-color: white;
font-size: 13px;
}

code.prettyprint {
background-color: white;
font-size: 13px;
}
</style>
<script type="text/javascript">var a="indexOf",b="&m=1",e="(^|&)m=",f="?",g="?m=1";function h(){var c=window.location.href,d=c.split(f);switch(d.length){case 1:return c+g;case 2:return 0<=d[1].search(e)?null:c+b;default:return null}}var k=navigator.userAgent;if(-1!=k[a]("Mobile")&&-1!=k[a]("WebKit")&&-1==k[a]("iPad")||-1!=k[a]("Opera Mini")||-1!=k[a]("IEMobile")){var l=h();l&&window.location.replace(l)};
</script><script type="text/javascript">
if (window.jstiming) window.jstiming.load.tick('headEnd');
</script></head>
<body class='loading variant-literate'>
<div class='navbar section' id='navbar'><div class='widget Navbar' id='Navbar1'><script type="text/javascript">
    function setAttributeOnload(object, attribute, val) {
      if(window.addEventListener) {
        window.addEventListener('load',
          function(){ object[attribute] = val; }, false);
      } else {
        window.attachEvent('onload', function(){ object[attribute] = val; });
      }
    }
  </script>
<div id="navbar-iframe-container"></div>
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<script type="text/javascript">
        gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() {
          if (gapi.iframes && gapi.iframes.getContext) {
            gapi.iframes.getContext().openChild({
                url: 'https://www.blogger.com/navbar.g?targetBlogID\0752481158163384033132\46blogName\75Java+Advent+Calendar\46publishMode\75PUBLISH_MODE_HOSTED\46navbarType\75LIGHT\46layoutType\75LAYOUTS\46searchRoot\75http://www.javaadvent.com/search\46blogLocale\75en\46v\0752\46homepageUrl\75http://www.javaadvent.com/\46targetPostID\758102289133489793686\46blogPostOrPageUrl\75http://www.javaadvent.com/2013/12/anatomy-of-java-decompiler.html\46blogFollowUrl\75https://plus.google.com/109896931373578063453\46vt\75-1722195604579494992',
                where: document.getElementById("navbar-iframe-container"),
                id: "navbar-iframe"
            });
          }
        });
      </script><script type="text/javascript">
(function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '//pagead2.googlesyndication.com/pagead/js/google_top_exp.js';
var head = document.getElementsByTagName('head')[0];
if (head) {
head.appendChild(script);
}})();
</script>
</div></div>
<div class='body-fauxcolumns'>
<div class='fauxcolumn-outer body-fauxcolumn-outer'>
<div class='cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left'>
<div class='fauxborder-right'></div>
<div class='fauxcolumn-inner'>
</div>
</div>
<div class='cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
</div>
<div class='content'>
<div class='content-fauxcolumns'>
<div class='fauxcolumn-outer content-fauxcolumn-outer'>
<div class='cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left'>
<div class='fauxborder-right'></div>
<div class='fauxcolumn-inner'>
</div>
</div>
<div class='cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
</div>
<div class='content-outer'>
<div class='content-cap-top cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left content-fauxborder-left'>
<div class='fauxborder-right content-fauxborder-right'></div>
<div class='content-inner'>
<header>
<div class='header-outer'>
<div class='header-cap-top cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left header-fauxborder-left'>
<div class='fauxborder-right header-fauxborder-right'></div>
<div class='region-inner header-inner'>
<div class='header section' id='header'><div class='widget Header' id='Header1'>
<div id='header-inner'>
<div class='titlewrapper'>
<h1 class='title'>
<a href='http://www.javaadvent.com/'>Java Advent Calendar</a>
</h1>
</div>
<div class='descriptionwrapper'>
<p class='description'><span>An advent calendar about the Java programming language, posting an interesting technical article from various authors related to Java daily between the 1st and 24th of December, each year.</span></p>
</div>
</div>
</div></div>
</div>
</div>
<div class='header-cap-bottom cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
</header>
<div class='tabs-outer'>
<div class='tabs-cap-top cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left tabs-fauxborder-left'>
<div class='fauxborder-right tabs-fauxborder-right'></div>
<div class='region-inner tabs-inner'>
<div class='tabs section' id='crosscol'><div class='widget HTML' id='HTML1'>
<div class='widget-content'>
<!-- generated by http://javascript.about.com/library/blcalgen.htm -->
<table id="month" style="width: 100%; text-align: right; background-color: lightgrey;">
<thead>
<tr>
<th class="weekend">Sunday</th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th class="weekend">Saturday</th>
</tr>
</thead>
<tbody>
<tr>
</tr><tr>
<td class="weekend" bgcolor="#AFCC6">1</td>
<td bgcolor="#AFCC6">2</td>
<td bgcolor="#AFCC6">3</td>
<td bgcolor="#AFCC6">4</td>
<td bgcolor="#AFCC6">5 <br/><a href="http://www.javaadvent.com/2014/12/jdk-9-letter-to-santa.html">JDK 9 - a letter to Santa?!</a></td>
<td bgcolor="#AFCC6">6 <br/> <a href="http://www.javaadvent.com/2014/12/recompiling-java-runtime-library-with.html"> Recompiling java runtime library with debug symbols</a></td>
<td class="weekend" bgcolor="#AFCC6">7 <br/> <a href="http://www.javaadvent.com/2014/12/mutation-testing-in-java-with-pit-and.html">Mutation testing in java with PIT and gradle</a></td>
</tr><tr>
<td class="weekend" bgcolor="#AFCC6">8 <br/> <a href="http://www.javaadvent.com/2014/12/creating-rest-api-with-spring-boot-and.html"> Creating REST API with Spring Boot and MongoDB</a></td>
<td bgcolor="#AFCC6">9 <br/> <a href="http://www.javaadvent.com/2014/12/own-your-heap-iterate-class-instances.html">Own your heap: Iterate class instances with JVMTI</a></td>
<td bgcolor="#AFCC6">10 <br/> <a href='http://www.javaadvent.com/2014/12/self-healing-applications-are-they-real.html'> Self healing applications are they real?</a></td>
<td bgcolor="#AFCC6">11 <br/><a href="http://www.javaadvent.com/2014/12/developers-want-to-be-heard.html"> Developers want to be heard!</a> <br/>  and <br/><a href="http://www.javaadvent.com/2014/12/how-and-why-is-unsafe-used-in-java.html"> How and Why is Unsage used in Java? </a></td>
<td bgcolor="#AFCC6">12 <br/> <a href="http://www.javaadvent.com/2014/12/lightweight-integration-with-java-ee-and-camel.html"> Lightweight Integration with Java EE and Camel</a></td>
<td bgcolor="#AFCC6">13 <br/><a href="http://www.javaadvent.com/2014/12/a-serpentine-path-to-music.html"> A serpentine path to music</a></td>
<td class="weekend" bgcolor="#AFCC6">14 <br/> <a href="http://www.javaadvent.com/2014/12/cms-pipelines-for-netrexx-on-jvm.html"> CMS pipelines for NetRexx on JVM</a></td>
</tr><tr>
<td class="weekend" bgcolor="#AFCC6">15 <br/> <a href="http://www.javaadvent.com/2014/12/thread-local-storage-in-java.html">Thread local storage in Java</a></td>
<td bgcolor="#AFCC6">16 <br/> <a href="http://www.javaadvent.com/2014/12/managing-package-dependencies-with.html"> Managing Package Dependencies with Degraph</a></td>
<td bgcolor="#AFCC6">17 <br/> <a href="http://www.javaadvent.com/2014/12/how-jooq-leverages-generic-type-safety.html">How jOOQ Leverages Generic Type Safety in its DSL</a></td>
<td bgcolor="#AFCC6">18 <br/> <a href="http://www.javaadvent.com/2014/12/how-jooq-allows-for-fluent-functional.html"> How jOOQ Allows for Fluent Functional-Relational Interactions in Java 8</a></td>
<td bgcolor="#AFCC6">19 <br/> <a href="http://www.javaadvent.com/2014/12/how-jooq-helps-pretend-that-your-stored.html">How jOOQ Helps Pretend that Your Stored Procedures are a Part of Java</a></td>
<td bgcolor="#AFCC6">20 <br/> <a href="http://www.javaadvent.com/2014/12/how-is-java-jvm-built-adopt-openjdk-is.html">How is Java/JVM built? Adopt OpenJDK is your answer!</a></td>
<td class="weekend" bgcolor="#AFCC6">21 <br/><a href="http://www.javaadvent.com/2014/12/doing-microservices-with-micro-infra.html#more"> Doing microservices with micro-infra</a></td>
</tr><tr>
<td class="weekend" bgcolor="#AFCC6">22 <a href="http://www.javaadvent.com/2014/12/a-persistent-keyvalue-server-in-40.html">A persistent KeyValue Server in 40 lines and a sad fact</a></td>
<td bgcolor="#AFCC6">23 <br/> <a href="http://www.javaadvent.com/2014/12/the-java-ecosystem-my-top-5-highlights.html"> The Java Ecosystem - My top 5 highlights of 2014</a></td>
<td bgcolor="#AFCC6">24<br/> <a href="http://www.javaadvent.com/2014/12/a-musical-finale.html"> A Musical Finale</a></td>
<td>25</td>
<td>26</td>
<td>27</td>
<td class="weekend">28</td>
</tr><tr>
<td class="weekend">29</td>
<td>30</td>
<td>31</td>
<td class="next">1</td>
<td class="next">2</td>
<td class="next">3</td>
<td class="weekend next">4</td>
</tr>
</tbody>
</table>
</div>
<div class='clear'></div>
<span class='widget-item-control'>
<span class='item-control blog-admin'>
<a class='quickedit' href='//www.blogger.com/rearrange?blogID=2481158163384033132&widgetType=HTML&widgetId=HTML1&action=editWidget&sectionId=crosscol' onclick='return _WidgetManager._PopupConfig(document.getElementById("HTML1"));' target='configHTML1' title='Edit'>
<img alt='' height='18' src='http://img1.blogblog.com/img/icon18_wrench_allbkg.png' width='18'/>
</a>
</span>
</span>
<div class='clear'></div>
</div></div>
<div class='tabs section' id='crosscol-overflow'></div>
</div>
</div>
<div class='tabs-cap-bottom cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
<div class='main-outer'>
<div class='main-cap-top cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left main-fauxborder-left'>
<div class='fauxborder-right main-fauxborder-right'></div>
<div class='region-inner main-inner'>
<div class='columns fauxcolumns'>
<div class='fauxcolumn-outer fauxcolumn-center-outer'>
<div class='cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left'>
<div class='fauxborder-right'></div>
<div class='fauxcolumn-inner'>
</div>
</div>
<div class='cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
<div class='fauxcolumn-outer fauxcolumn-left-outer'>
<div class='cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left'>
<div class='fauxborder-right'></div>
<div class='fauxcolumn-inner'>
</div>
</div>
<div class='cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
<div class='fauxcolumn-outer fauxcolumn-right-outer'>
<div class='cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left'>
<div class='fauxborder-right'></div>
<div class='fauxcolumn-inner'>
</div>
</div>
<div class='cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
<!-- corrects IE6 width calculation -->
<div class='columns-inner'>
<div class='column-center-outer'>
<div class='column-center-inner'>
<div class='main section' id='main'><div class='widget Blog' id='Blog1'>
<div class='blog-posts hfeed'>
<!-- google_ad_section_start(name=default) -->

          <div class="date-outer">
        
<h2 class='date-header'><span>Tuesday, December 10, 2013</span></h2>

          <div class="date-posts">
        
<div class='post-outer'>
<div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'>
<meta content='http://3.bp.blogspot.com/-EhdcJg9B53U/Up9ExK_sHHI/AAAAAAAAAYY/1svdXdlriXc/s72-c/fn.png' itemprop='image_url'/>
<meta content='2481158163384033132' itemprop='blogId'/>
<meta content='8102289133489793686' itemprop='postId'/>
<a name='8102289133489793686'></a>
<h3 class='post-title entry-title' itemprop='name'>
Anatomy of a Java Decompiler
</h3>
<div class='post-header'>
<div class='post-header-line-1'></div>
</div>
<div class='post-body entry-content' id='post-body-8102289133489793686' itemprop='description articleBody'>
<div dir="ltr" style="text-align: left;" trbidi="on">
<style>
  pre { font-size: 9pt; }
  code { font-size: 9pt; }
</style>
<p><em>Mike Strobel &amp; Lee Benfield</em></p>

<!-- LB - Scroll down to 'what's with all these lists&#8230;. when you want to add graphs -->


<p>A decompiler, simply put, attempts to reverse the transformation of source code to object code.  But there are many interesting complexities&mdash;Java source code is structured; bytecode certainly isn't.  Moreover, the transformation isn't one-to-one: two different Java programs may yield identical bytecode.  We need to apply heuristics in order to get a reasonable approximation of the original source.</p>

<h3>(A Tiny) Bytecode Refresher</h3>

<p>In order to understand how a decompiler works, it's necessary to understand the basics of byte code.  If you&#8217;re already familiar with byte code, feel free to skip ahead to the next section.</p>

<p>The JVM is a <em>stack-based machine</em> (as opposed to a register-based machine), meaning instructions operate on an evaluation stack.  Operands may be popped off the stack, various operations performed, and the results pushed back onto the stack for further evaluation.  Consider the following method:</p>

<pre class="prettyprint">
public static int plus(int a, int b) {
    int c = a + b;
    return c;
}
</pre>


<p><sup><em>Note: All byte code shown in this article is output from <code>javap</code>, e.g., <code>javap -c -p MyClass</code>.</em></sup></p>

<pre class="prettyprint">
public static int plus(int, int);
 Code:
  stack=2, locals=3, arguments=2
   0: iload_0    // load &#8216;x&#8217; from slot 0, push onto stack
   1: iload_1    // load &#8216;y&#8217; from slot 1, push onto stack
   2: iadd       // pop 2 integers, add them together, and push the result
   3: istore_2   // pop the result, store as &#8216;sum&#8217; in slot 2
   4: iload_2    // load &#8216;sum&#8217; from slot 2, push onto stack
   5: ireturn    // return the integer at the top of the stack
</pre>


<p><sup><em>(Comments added for clarity.)</em></sup></p>

<p>A method's local variables (including arguments to the method) are stored in what the JVM refers to as the <em>local variable array</em>.  We'll refer to a value (or reference) stored in location <code>#x</code> in the local variable array as `slot #x' for brevity (see <a href="http://docs.oracle.com/javase/specs/jvms/se5.0/html/Overview.doc.html#15722">JVM Specification &#x00A7;3.6.1</a>).</p>

<p>For instance methods, the value in slot #0 is always the <code>this</code> pointer.  Then come the method arguments, from left to right, followed by any local variables declared within the method.  In the example above, the method is static, so there is no <code>this</code> pointer; slot #0 holds parameter <code>x</code>, and slot #1 holds parameter <code>y</code>.  The local variable <code>sum</code> resides in slot #2.</p>

<p>It's interesting to note that each method has a max stack size and max local variable storage, both of which are determined at compile time.</p>

<p>One thing that's immediately obvious from here, which you might not initially expect, is that the compiler made no attempt to optimise the code.   In fact, <code>javac</code> almost never emits optimized bytecode.  This has multiple benefits, including the ability to set breakpoints at most locations: if we were to eliminate the redundant load/store operations, we'd lose that capability.  Thus, most of the heavy lifting is performed at runtime by a just-in-time (JIT) compiler.</p>

<h3>Decompiling</h3>

<p>So, how can you take unstructured, stack-based byte code and translate it back into structured Java code?  One of the first steps is usually to get rid of the operand stack, which we do by mapping stack values to variables and inserting the appropriate load and store operations.</p>

<p>A 'stack variable' is only assigned once, and consumed once.  You might note that this will lead to a <em>lot</em> of redundant variables&mdash;more on this later!  The decompiler may also reduce the byte code into an even simpler instruction set, but we won't consider that here.</p>

<!-- LB: I'm suing this notation rather than Stack_0_2 etc for brevity, and so we can make screens wider -->


<p>We'll use the notation <code>s0</code> (etc.) to represent <em>stack variables</em>, and <code>v0</code> to represent true local variables referenced in the original byte code (and stored in slots).</p>

<!-- LB: Mou's tables aren't quite good enough, so I've used raw html.  Yes, it's a pain.  But it comes out pretty nice.  Keep them narrow enough that nothing wraps, even on a 1/2 screen mou preview. -->




<table style="border: 0px; font-size: 9pt;">
<tr>
<th style="padding: 0em 2em 0em 0em; text-align: left;"/>
<th style="padding: 0em 2em 0em 0em; text-align: left;">Bytecode</th>
<th style="padding: 0em 2em 0em 0em; text-align: left;">Stack Variables</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">Copy Propagation</th>
</tr>
<tr>
<td valign="top">
<font face="monospace">
0<br/>
1<br/>
2<br/>
3<br/>
4<br/>
5<br/>
</font>
</td>

<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
iload_0<br/>
iload_1<br/>
iadd<br/>
istore_2<br/>
iload_2<br/>
ireturn<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
s0 = v0<br/>
s1 = v1<br/>
s2 = s0 + s1<br/>
v2 = s2<br/>
s3 = v2<br/>
return s3<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
<br/>
<br/>
<br/>
v2 = v0 + v1<br/>
<br/>
return v2<br/>
</font>
</td>
</tr>
</table>


<p>We get from <em>bytecode</em> to <em>variables</em> by assigning identifiers to every value pushed or popped, e.g., <code>iadd</code> pops two operands to add and pushes the result.</p>

<p>We then apply a technique called <em>copy propagation</em> to eliminate some of the redundant variables.  Copy propagation is a form of inlining in which references to variables are simply replaced with the assigned value, provided the transformation is valid.</p>

<p>What do we mean by "valid"?  Well, there are some important restrictions.  Consider the following:</p>

<pre><code>0: s0 = v1
1: v1 = s4
2: v2 = s0 &lt;-- s0 cannot be replaced with v1
</code></pre>

<p>Here, if we were to replace <code>s0</code> with <code>v0</code>, the behavior would change, as the value of <code>v0</code> changes after <code>s0</code> is assigned, but before it is consumed.  To avoid these complications, we only use copy propagation to inline variables that are assigned <em>exactly once</em>.</p>

<p>One way to enforce this might be to track all stores to non-stack variables, i.e., we know that <code>v1</code> is assigned v1<sub>0</sub> at #0, and also v1<sub>1</sub> at #2.  Since there is more than one assignment to <code>v1</code>,  we cannot perform copy propagation.</p>

<p>Our original example, however, has no such complications, and we end up with a nice, concise result:</p>

<pre><code>v2 = v0 + v1
return v2
</code></pre>

<h3>Aside: Restoring Variable Names</h3>

<p>If variables are reduced to slot references in the byte code, how then do we restore the original variable names?  It's possible we can't.  To improve the debugging experience, the byte code for each method may include a special section called the <em>local variable table</em>.  For each variable in the original source, there exists an entry that specifys the name, the slot number, and the bytecode range for which the name applies.  This table (and other useful metadata) can be included in the <code>javap</code> disassembly by including the <code>-v</code> option.  For our <code>plus()</code> method above, the table looks like this:</p>

<pre><code>Start  Length  Slot  Name   Signature
0      6       0     a      I
0      6       1     b      I
4      2       2     c      I
</code></pre>

<p>Here, we see that <code>v2</code> refers to an integer variable originally named '<code>c</code>' at bytecode offsets #4-5.</p>

<p>For classes that have been compiled without local variable tables (or which had them stripped out by an obfuscator), we have to generate our own names.  There are many strategies for doing this; a clever implementation might look at how a variable is used for hints on an appropriate name.</p>

<h3>Stack Analysis</h3>

<p>In the previous example, we could guarantee which value was on top of the stack at any given point, and so we could name <code>s0</code>, <code>s1</code>, and so on.</p>

<p>So far, dealing with variables has been pretty straightforward because we've only explored methods with a single code path.  In a real world application, most methods aren't going to be so accommodating.  Each time you add a loop or condition to a method, you increase the number of possible paths a caller might take.  Consider this modified version of our earlier example:</p>

<pre class="prettyprint">
public static int plus(boolean t, int a, int b) {
    int c = t ? a : b;
    return c;
}
</pre>


<p>Now we have control flow to complicate things; if try to perform the same assignments as before, we run into a problem.</p>

<table style="border: 0px; font-size: smaller;">
<tr>
<th style="padding: 0em 2em 0em 0em; text-align: left;" />
<th style="padding: 0em 2em 0em 0em; text-align: left;">Bytecode</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">Stack Variables</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 1em 0em 0em;">
<font face="monospace">
0<br/>
1<br/>
4<br/>
5<br/>
8<br/>
9<br/>
10<br/>
11<br/>
</font>
</td>

<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
iload_0<br/>
ifeq 8<br/>
iload_1<br/>
goto 9<br/>
iload_2<br/>
istore_3<br/>
iload_3<br/>
ireturn<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
s0 = v0<br/>
if (s0 == 0) goto #8<br/>
s1 = v1<br/>
goto #9<br/>
s2 = v2<br/>
v3 = {s1,s2}<br/>
s4 = v3<br/>
return s4<br/>
</font>
</td>
</tr>
</table>


<p>We need to be a little smarter about how we assign our stack identifiers.  It's no longer sufficient to consider each instruction on its own; we need to keep track of how the stack looks at any given location, because there are multiple paths we might take to get there.</p>

<p>When we examine <code>#9</code>, we see that <code>istore_3</code> pops a single value, but that value has two sources: it might have originated at either <code>#5</code> or <code>#8</code>.  The value at the top of the stack at <code>#9</code> might be either <code>s1</code> or <code>s2</code>, depending on whether we came from <code>#5</code> or <code>#8</code>, respectively.  Therefore, we need to consider these to be the same variable&mdash;we merge them, and all references to <code>s1</code> or <code>s2</code> become references to the unambiguous variable <code>s{1,2}</code>.  After this 'relabeling', we can safely perform copy propagation.</p>

<table style="border: 0px; font-size: smaller;">
<tr>
<th style="padding: 0em 2em 0em 0em; text-align: left;" />
<th style="padding: 0em 2em 0em 0em; text-align: left;">After Relabeling</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">After Copy Propagation</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 1em 0em 0em;">
<font face="monospace">
0<br/>
1<br/>
4<br/>
5<br/>
8<br/>
9<br/>
10<br/>
11<br/>
</font>
</td>

<td valign="top" valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
s0 = v0<br/>
if (s0 == 0) goto #8<br/>
s{1,2} = v1<br/>
goto #9<br/>
s{1,2} = :v2<br/>
v3 = s{1,2}<br/>
s4 = v3<br/>
return s4<br/>
</font>
</td>
<td>
<font face="monospace">
<br/>
if (v0 == 0) goto #8<br/>
s{1,2} = v1<br/>
goto #9<br/>
s{1,2} = v2<br/>
v3 = s{1,2}<br/>
<br/>
return v3<br/>
</font>
</td>
</tr>
</table>


<p>Notice the conditional branch at <code>#1</code>: if the value of <code>s0</code> is zero, we jump to the <code>else</code> block; otherwise, we continue along the current path.  It's interesting to note that the test condition is negated when compared to the original source.</p>

<p>We've now covered enough to dive into...</p>

<h3>Conditional Expressions</h3>

<!-- LB : At this point, we might want to introduce a few graphviz images.
 If you do that, comment out the code blocks below, rather than dropping them, as we may end up iterating.
 -->


<p>At this point, we can determine that our code could be modeled with a ternary operator (<code>?:</code>): we have a conditional, with each branch having a single assignment to the same stack variable s{1,2}, after which the two paths converge.</p>

<p>Once we've identified this pattern, we can roll the ternary up straight away.</p>

<table style="border: 0px; font-size: smaller;">
<tr>
<th style="padding: 0em 2em 0em 0em; text-align: left;" />
<th style="padding: 0em 2em 0em 0em; text-align: left;">After Copy Prop.</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">Collapse Ternary</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 1em 0em 0em;">
<font face="monospace">
0<br/>
1<br/>
4<br/>
5<br/>
8<br/>
9<br/>
10<br/>
11<br/>
</font>
</td>

<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
<br/>
if (v0 == 0) goto #8<br/>
s{1,2} = v1<br/>
goto 9<br/>
s{1,2} = v2<br/>
v3 = s{1,2}<br/>
<br/>
return v3<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
<br/>
<br/>
<br/>
<br/>
<br/>
v3 = v0 != 0 ? v1 : v2<br/> 
<br/>
return v3<br/>
</font>
</td>

</tr>
</table>


<p>Note that, as part of the transformation, we negated the condition at <code>#9</code>.  It turns out that <code>javac</code> is fairly predictable in how it negates conditions, so we can more closely matche the original source if we flip those conditions back.</p>

<!-- LB: I think this IS worth having.  Ideally, I'd have it in a sidebar, but that's a bit complex for this layout -->


<h3>Aside - But what are the types?</h3>

<p>When dealing with stack values, the JVM uses a more simplistic type system than Java source.  Specifically, <code>boolean</code>, <code>char</code>, and <code>short</code> values are manipulated using the same instructions as <code>int</code> values.  Thus, the comparison <code>v0 != 0</code> could be interpreted as either:</p>

<p><code>v0 != false ? v1 : v2</code>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<em>...or:</em>
<br/>
<code>v0 != 0 ? v1 : v2</code>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<em>...or even:</em>
<br/>
<code>v0 != false ? v1 == true : v2 == true</code>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<em>...and so on!</em></p>

<p>In this case, however, we are fortunate to know the exact type of <code>v0</code>, as it is contained within the <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method descriptor</a>:</p>

<pre><code>    descriptor: (ZII)I
    flags: ACC_PUBLIC, ACC_STATIC
</code></pre>

<p>This tells us the method signature is of the form:</p>

<pre><code>    public static int plus(boolean, int, int)
</code></pre>

<p>We can also infer that <code>v3</code> should be an <code>int</code> (as opposed to a <code>boolean</code>) because it is used as the return value, and the descriptor tells us the return type.  We are then left with:</p>

<pre><code>v3 =  v0 ? v1 : v2
return v3
</code></pre>

<p>As an aside, if <code>v0</code> were a local variable (and not a formal parameter) then we might not know it represents a <code>boolean</code> value and not an <code>int</code>.  Remember that local variable table we mentioned earlier, which tells us the original variable names?  It also includes information about the variable <em>types</em>, so if your compiler is configured to emit debug information, we can look to that table for type hints.  There is another, similar table called <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html">LocalVariableTypeTable</a> that contains similar information; the key difference is that a <code>LocalVariableTypeTable</code> may include detailed information about generic types, whereas a <code>LocalVariableTable</code> cannot.  It's worth noting that these tables are <em>unverified</em> metadata, so they <strong>are not necessarily trustworthy</strong>.  A particularly devious obfuscator might choose to fill these tables with lies, and the resulting bytecode would still be valid!  Use them at your own discretion.</p>

<h3>Short-Circuit Operators (<code>'&amp;&amp;'</code> and <code>'||'</code>)</h3>

<pre class="prettyprint">
public static boolean fn(boolean a, boolean b, boolean c){
    return a || b && c;
}
</pre>


<p>How could anything be simpler?  The bytecode is, unfortunately, a bit of a pain...</p>

<table style="border: 0px; font-size: smaller;">
<tr>
<th style="padding: 0em 2em 0em 0em; text-align: left;"/>
<th style="padding: 0em 2em 0em 0em; text-align: left;">Bytecode</th>
<th style="padding: 0em 2em 0em 0em; text-align: left;">Stack Variables</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">After Copy Propagation</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 1em 0em 0em;">
<font face="monospace">
0<br/>
1<br/>
4<br/>
5<br/>
8<br/>
9<br/>
12<br/>
13<br/>
16<br/>
17<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
iload_0<br/>
ifne          #12<br/>
iload_1<br/>
ifeq          #16<br/>
iload_2<br/>        
ifeq          #16<br/>
iconst_1<br/>       
goto          #17<br/>
iconst_0<br/>       
ireturn<br/>        
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
s0 = v0<br/>
if (s0 != 0) goto #12<br/>
s1 = v1<br/>
if (s1 == 0) goto #16<br/>
s2 = v2<br/>
if (s2 == 0) goto #16<br/>
s3 = 1<br/>
goto 17<br/>
s4 = 0<br/>
return s{3,4}<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
<br/>
if (v0 != 0) goto #12<br/>
<br/>
if (v1 == 0) goto #16<br/>
<br/>
if (v2 == 0) goto #16<br/>
s{3,4} = 1<br/>
goto 17<br/>
s{3,4} = 0<br/>
return s{3,4}<br/>
</font>
</td>

</tr>
</table>


<p>The <code>ireturn</code> instruction at <code>#17</code> could return either <code>s3</code> or <code>s4</code>, depending on what path is taken.  We alias them as described above, and then we perform copy propagation to eliminate <code>s0</code>, <code>s1</code>, and <code>s2</code>.</p>

<p>We are left with three consecutive conditionals at <code>#1</code>, <code>#5</code> and <code>#7</code>.  As we mentioned earlier, conditional branches either jump or fall through to the next instruction.</p>

<p>The bytecode above contains sequences of conditional branches that follow specific and very useful patterns:</p>

<table style="border: 0px; font-size: smaller; margin: auto;">
<tr>
<th style="padding: 0em 4em 0em 0em; text-align: left;">Conditional Conjunction (&&)</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">Conditional Disjunction (||)</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<pre class="prettyprint">
T1: 
  if (c1) goto L1
  if (c2) goto L2
L1:
  ...

Becomes

  if (!c1 && c2) goto L2
L1:
  ...
</pre>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
<pre class="prettyprint">
T1:
  if (c1) goto L2
  if (c2) goto L2
L1:
  ...
  
Becomes

  if (c1 || c2) goto L2
L1:
  ...
</pre>
</font>
</td>
</tr>
</table>


<p>If we consider neighbouring pairs of conditionals above, <code>#1...#5</code> do not conform to either of these patterns, but <code>#5...#9</code> is a conditional disjunction (<code>||</code>), so we apply the appropriate transformation:</p>

<pre class="prettyprint">
 1:  if (v0 != 0) goto #12
 5:  if (v1 == 0 || v2 == 0) goto #16
12:  s{3,4} = 1
13:  goto #17
16:  s{3,4} = 0
17:  return s{3,4}
</pre>


<p>Note that every transform we apply might create opportunities to perform <em>additional</em> transforms.  In this case, applying the <code>||</code> transform restructured our conditions, and now <code>#1...#5</code> conform to the <code>&amp;&amp;</code> pattern!  Thus, we can further simplify the method by combining these lines into a single conditional branch:</p>

<pre class="prettyprint">
 1:  if (v0 == 0 && (v1 == 0 || v2 == 0)) goto #16
12:  s{3,4} = 1
13:  goto #17
16:  s{3,4} = 0
17:  return s{3,4}
</pre>


<p>Does this look familiar?  It should: this bytecode now conforms to the ternary (<code>?:</code>) operator pattern we covered earlier.  We can reduce <code>#1...#16</code> to a single expression, then use copy propagation to inline <code>s{3,4}</code> into the <code>return</code> statement at <code>#17</code>:</p>

<pre class="prettyprint">
return (v0 == 0 && (v1 == 0 || v2 == 0)) ? 0 : 1;
</pre>


<p>Using the method descriptor and local variable type tables described earlier, we can infer all the types necessary to reduce this expression to:</p>

<pre class="prettyprint">
return (v0 == false && (v1 == false || v2 == false)) ? false : true;
</pre>


<p>Well, this is certainly more concise than our original decompilation, but it's still pretty jarring.  Let's see what we can do about that.  We can start by collapsing comparisons like <code>x == true</code> and <code>x == false</code> to <code>x</code> and <code>!x</code>, respectively.  We can also eliminate the ternary operator by reducing <code>x ? false : true</code> as the simple expression <code>!x</code>.</p>

<pre class="prettyprint">
return !(!v0 && (!v1 || !v2));
</pre>


<p>Better, but it's still a of a handful.  If you remember your high school discrete maths, you can see that De Morgan's theorem can be applied here:</p>

<pre><code>    !(a || b) --&gt; (!a) &amp;&amp; (!b)
    !(a &amp;&amp; b) --&gt; (!a) || (!b)
</code></pre>

<p>And thus:</p>

<pre class="prettyprint">
return ! ( !v0 && ( !v1 || !v2 ) )
</pre>


<p>...becomes:</p>

<pre class="prettyprint">
return ( v0 || !(!v1 || !v2 ) )
</pre>


<p>...and eventually:</p>

<pre class="prettyprint">
return ( v0 || (v1 && v2) )
</pre>


<p>Hurrah!</p>

<h3>Dealing with Method Calls</h3>

<p>We've already seen what it looks like for a method to be called: arguments 'arrive' in the locals array.  To <em>call</em> a method, arguments must be pushed onto the stack, following a <code>this</code> pointer in the case of for instance methods).  Calling a method in bytecode is as you'd expect:</p>

<pre><code>    push arg_0
    push arg_1 
    invokevirtual METHODREF
</code></pre>

<p>We've specified <code>invokevirtual</code> above, which is the instruction used to invoke most instance methods.  The JVM actually has a handful of instructions used for method calls, each with different semantics:</p>

<ol>
<li><p> <code>invokeinterface</code> invokes interface methods.</p></li>
<li><p> <code>invokevirtual</code> invokes instance methods using virtual semantics, i.e., the call is dispatched to the proper override based on the runtime type of the target.</p></li>
<li><p> <code>invokespecial</code> invokes invokes a <em>specific</em> instance method (without virtual sematics); it is most commonly used for invoking constructors, but is also used for calls like <code>super.method()</code>.</p></li>
<li><p> <code>invokestatic</code> invokes static methods.</p></li>
<li><p> <code>invokedynamic</code> is the least common (in Java), and it uses a 'bootstrap' method to invoke a custom call site binder.  It was created to improve support for dynamic languages, and has been used in Java 8 to implement lambdas.</p></li>
</ol>


<p>The important detail for a decompiler writer is that the class's <em>constant pool</em> contains details for any method called, including the number and type of its arguments, as well as its return type.  Recording this information in the caller class allows the runtime to verify that the intended method exists at runtime, and that it conforms to the expected signature.  If the target method is in third party code, and its signature changes, then any code that attempts to call the old version will throw an error (as opposed to producing undefined behavior).</p>

<p>Going back to our example above, the presence of the <code>invokevirtual</code> opcode tells us that the target method is an <em>instance method</em>, and therefore requires a <code>this</code> pointer as an implicit first argument.  The <code>METHODREF</code> in the constant pool tells us that the method has one formal parameter, so we know we need to pop an argument off of the stack in addition to the target instance pointer.  We can then rewrite the code as:</p>

<pre><code>    arg_0.METHODREF(arg_1)
</code></pre>

<p>Of course, bytecode isn't always so friendly; there's no requirement that stack arguments be pushed neatly onto the stack, one after the other.  If, for example, one of the arguments was a ternary expression, then there would be intermediate load, store, and branch instructions that will need to be transformed independently.  Obfuscators might rewrite methods into a particularly convoluted sequence of instructions.  A good decompiler will need to be flexible enough to handle many interesting edge cases that are beyond the scope of this article.</p>

<h3>There has to be more to it than this...</h3>

<p>So far, we've limited ourselves to analyzing a single sequence of code, beginning with a list of simple instructions and applying transformations that produce more familiar, higher-level constructs.  If you are thinking that this seems a little too simplistic, then you are correct.   Java is a highly structured language with concepts like scopes and blocks, as well as more complicated control flow mechanisms.  In order to deal with constructs like <code>if/else</code> blocks and loops, we need to perform a more rigorous analysis of the code, paying special attention to the various paths that might be taken.  This is called <em>control flow analysis</em>.</p>

<p>We begin by breaking down our code into contiguous blocks that are guaranteed to execute from beginning to end.  These are called <em>basic blocks</em>, and we construct them by splitting up our instruction list along places where we might jump to another block, as well as any instructions which might be jump targets themselves.</p>

<p>We then build up a <em><a href="https://en.wikipedia.org/wiki/Control_flow_graph">control flow graph</a></em> (CFG) by creating edges between the blocks to represent all possible branches.  Note that these edges may not be <em>explicit</em> branches; blocks containing instructions that might throw exceptions will be connected to their respective exception handlers.  We won't go into detail about constructing CFGs, but some high level knowledge is required to understand how we use these graphs to detect code constructs like loops.</p>

<p style="text-align: center;">
<a target="#new" href="https://upload.wikimedia.org/wikipedia/commons/2/26/Simplified_Control_Flowgraphs.jpg">
<img alt="[Control Flow Graph Examples]" src="https://upload.wikimedia.org/wikipedia/commons/2/26/Simplified_Control_Flowgraphs.jpg" width="480" height="240" style="border: 1px solid black;" />
</a>
<br/>
<sub><em>Examples of control flow graphs.</em></sub>
</p>


<p>The aspects of control flow graphs that we are most interested in are <em>domination relationships</em>:</p>

<ul>
<li><p>A node <code>D</code> is said to <em>dominate</em> another node <code>N</code> if all paths to <code>N</code> pass through <code>D</code>.  All nodes dominate themselves; if <code>D</code> and <code>N</code> are different nodes, then <code>D</code> is said to <em>strictly dominate</em> <code>N</code>.</p></li>
<li><p>If <code>D</code> strictly dominates <code>N</code> and does <em>not</em> strictly dominate any <em>other</em> node that strictly dominates <code>N</code>, then <code>D</code> can be said to <em>immediately dominate</em> <code>N</code>.</p></li>
<li><p>The <em>dominator tree</em> is a tree of nodes in which each node's children are the nodes it immediately dominates.</p></li>
<li><p>The <em>dominance frontier</em> of <code>D</code> is the set of all nodes <code>N</code> such that <code>D</code> dominates an immediate predecessor of <code>N</code> but does not strictly dominate <code>N</code>.  In other words, it is the set of nodes where <code>D</code>'s dominance ends.</p></li>
</ul>


<!--
As such, we have a forward edge (jump to a later instruction) or a back edge (jump to a previous instruction) - **but of course**, this assumes that opcode ordering has meaning - if we make these assumptions, an obfuscator could randomly shuffle instructions to confuse us.  Because of this, you may want to apply a topological sort to your instruction graph.  (Or apply the sort if you find that you can't get good decompilation *without* sorting.) 
-->


<!-- LB - Mike - insert a graph or two here &#8230;. -->


<h3>Basic Loops and Control Flow</h3>

<!--
Consider the following Java method and disassembly:

<table style="border: 0px; font-size: smaller; margin: auto;">
<tr>
<th style="padding: 0em 4em 0em 0em; text-align: left;">Original Source</th>
<th style="padding: 0em 0em 0em 0em; text-align: left;">Disassembly</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 4em 0em 0em;">
<pre>
public static void fn(int n){
    for (int i = 0; i < n; ++i) {
        System.out.println(i);
    }
}
</pre>
</td>
<td valign="top">
<pre>
 0:  iconst_0
 1:  istore_1
 2:  iload_1
 3:  iload_0
 4:  if_icmpge 20
 7:  getstatic #2      // System.out
10:  iload_1
11:  invokevirtual #3  // PrintStream.println:(I)V
14:  iinc 1, 1
17:  goto 2
20:  return   
</pre>
</td>
</tr>
</table>
-->


<p>Consider the following Java method:</p>

<pre class="prettyprint">
public static void fn(int n) {
    for (int i = 0; i < n; ++i) {
        System.out.println(i);
    }
}
</pre>


<p>...and its disassembly:</p>

<pre class="prettyprint">
 0:  iconst_0
 1:  istore_1
 2:  iload_1
 3:  iload_0
 4:  if_icmpge 20
 7:  getstatic #2      // System.out:PrintStream
10:  iload_1
11:  invokevirtual #3  // PrintStream.println:(I)V
14:  iinc 1, 1
17:  goto 2
20:  return   
</pre>


<p>Let's apply what we discussed above to convert this into a more readable form, first by introducing stack variables, then performing copy propagation.</p>

<table style="border: 0px; font-size: smaller;">
<tr>
<th style="padding: 0em 1em 0em 0em; text-align: left;" />
<th style="padding: 0em 4em 0em 0em; text-align: left;">Bytecode</th>
<th style="padding: 0em 4em 0em 0em; text-align: left;">Stack Variables</th>
<th style="padding: 0em 4em 0em 0em; text-align: left;">After Copy Propagation</th>
</tr>
<tr>
<td valign="top" style="padding: 0em 1em 0em 0em;">
<font face="monospace">
&nbsp;0<br/>
&nbsp;1<br/>
&nbsp;2<br/>
&nbsp;3<br/>
&nbsp;4<br/>
&nbsp;7<br/>
10<br/>
11<br/>
14<br/>
17<br/>
20<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
iconst_0<br/>    
istore_1<br/>    
iload_1<br/>      
iload_0<br/>      
if_icmpge 20<br/>
getstatic #2<br/>
iload_1<br/>
invokevirtual #3<br/>
iinc 1, 1<br/>
goto 2<br/>
return<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
s0 = 0<br/>    
v1 = s0<br/>    
s2 = v1<br/>      
s3 = v0<br/>      
if (s2 >= s3) goto 20<br/>
s4 = System.out<br/>
s5 = v1<br/>
s4.println(s5)<br/>
v1 = v1 + 1<br/>
goto 2<br/>
return<br/>
</font>
</td>
<td valign="top" style="padding: 0em 2em 0em 0em;">
<font face="monospace">
<br/>    
v1 = 0<br/>    
<br/>      
<br/>      
if (v1 >= v0) goto 20<br/>
<br/>
<br/>
System.out.println(v1)<br/>
v1 = v1 + 1<br/>
goto 4<br/>
return<br/>
</font>
</td>
</tr>
</table>


<p></p>

<p>Notice how the conditional branch at <code>#4</code> and the <code>goto</code> at <code>#17</code> create a logical loop.  We can see this more easily by looking at a control flow graph:</p>

<!-- LB - Mike - graph here -->


<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-EhdcJg9B53U/Up9ExK_sHHI/AAAAAAAAAYY/1svdXdlriXc/s1600/fn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-EhdcJg9B53U/Up9ExK_sHHI/AAAAAAAAAYY/1svdXdlriXc/s1600/fn.png" /></a></div>


<p>From the graph, it's obvious that we have a neat cycle, with an edge from the <code>goto</code> back to a conditional branch.  In this case, the conditional branch is referred to as a <em>loop header</em>, which can be defined as a dominator with a loop-forming backward edge.  A loop header dominates all nodes within the loop's body.</p>

<p>We can determine whether a condition is a loop header by looking for a loop-forming back edge, but how do we do that?  A simple solution is to test whether the condition node is in its own dominance frontier.  Once we know we have a loop header, we have to figure out which nodes to pull into the loop body; we can do that by finding all nodes dominated by the header.  In pseudocode, our algorithm would look something like this:</p>

<pre><code>    findDominatedNodes(header)
        q := new Queue()
        r := new Set()

        q.enqueue(header)

        while (not q.empty())
            n := q.dequeue()

            if (header.dominates(n))
                r.add(n)

                for (s in n.successors())
                    q.enqueue(n)

        return r
</code></pre>

<p>Once we've figured out the loop body, we can transform our code into a loop.  Keep in mind that our loop header may be a conditional jump <em>out</em> of the loop, in which case we need to negate the condition.</p>

<pre class="prettyprint">
v1 = 0
while (v1 < v0) {
    System.out.println(v1)
    v1 = v1 + 1
}
return
</pre>


<p>And voila, we have a simple pre-condition loop!  Most loops, including <code>while</code>, <code>for</code> and <code>for-each</code>, compile down to the same basic pattern, which we detect as a simple <code>while</code> loop.  There's no way to know for sure what kind of loop the programmer originally wrote, but <code>for</code> and <code>for-each</code> follow pretty specific patterns that we can look for.  We won't go into the details, but if you look at the <code>while</code> loop above, you can see how the original <code>for</code> loop's initializer (<code>v1 = 0</code>) precedes the loop, and its iterator (<code>v1 = v1 + 1</code>) has been inserted at the end of the loop body.  We'll leave it as an exercise to think about when and how one might transform <code>while</code> loops into <code>for</code> or <code>for-each</code>.  It's also interesting to think about how we might have to adjust our logic to detect <em>post-conditional</em> (<code>do/while</code>) loops.</p>

<p>We can apply a similar technique to decompile <code>if/else</code> statements.  The bytecode pattern is pretty straightforward:</p>

<pre class="prettyprint">
begin:
    iftrue(!condition) goto #else
    // `if` block begins here
    ...
    goto #end
    
else:
    // `else` block begins here
    ...
    
end:
    // end of `if/else`
</pre>


<p>Here, we use <code>iftrue</code> as a pseudo-instruction to represent any conditional branch: test a condition, and if it passes, then branch; otherwise, continue.  We know that the <code>if</code> block starts at the instruction following the condition, and the <code>else</code> block starts at the condition's jump target.  Finding the contents of those blocks is as simple as finding the nodes dominated by those starting nodes, which we can do using the same algorithm we described above.</p>

<p>We've now covered basic control flow mechanisms, and while there are others (e.g., exception handlers and subroutines), those are beyond the scope of this introductory article.</p>

<h3>Wrap-Up</h3>

<p>Writing a decompiler is no simple task, and the experience easily translates into a book's worth of material&mdash;perhaps even a series of books!  Obviously, we could not cover everything in a single blog post, and you probably wouldn't want to read it if we'd tried.  We hope that by touching on the most common constructs&mdash;logical operators, conditionals, and basic control flow&mdash;we have given you an interesting glimpse into the world of decompiler development.</p>

<p><strong>Lee Benfield</strong> is the author of the <a href="http://www.benf.org/other/cfr">CFR</a> Java decompiler.<br/>
<strong>Mike Strobel</strong> is the author of <a href="https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler">Procyon</a>, a Java decompiler and metaprogramming framework.</p>

<p>Now go write your own! :)</p>

<p><em>This post is part of the&nbsp;<a href="http://javaadvent.com/">Java Advent Calendar</a>&nbsp;and is licensed under the&nbsp;<a href="https://creativecommons.org/licenses/by/3.0/">Creative Commons 3.0 Attribution</a>&nbsp;license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on!</em></div></p>
<div style='clear: both;'></div>
</div>
<div class='post-footer'>
<div class='post-footer-line post-footer-line-1'><span class='post-author vcard'>
Posted by
<span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'>
<meta content='http://www.blogger.com/profile/10732477960055957828' itemprop='url'/>
<a href='http://www.blogger.com/profile/10732477960055957828' rel='author' title='author profile'>
<span itemprop='name'>Mike Strobel</span>
</a>
</span>
</span>
<span class='post-comment-link'>
</span>
<span class='post-icons'>
<span class='item-control blog-admin pid-1632808286'>
<a href='http://www.blogger.com/post-edit.g?blogID=2481158163384033132&postID=8102289133489793686&from=pencil' title='Edit Post'>
<img alt='' class='icon-action' height='18' src='http://img2.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/>
</a>
</span>
</span>
<div class='post-share-buttons goog-inline-block'>
<a class='goog-inline-block share-button sb-email' href='http://www.blogger.com/share-post.g?blogID=2481158163384033132&postID=8102289133489793686&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='http://www.blogger.com/share-post.g?blogID=2481158163384033132&postID=8102289133489793686&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='http://www.blogger.com/share-post.g?blogID=2481158163384033132&postID=8102289133489793686&target=twitter' target='_blank' title='Share to Twitter'><span class='share-button-link-text'>Share to Twitter</span></a><a class='goog-inline-block share-button sb-facebook' href='http://www.blogger.com/share-post.g?blogID=2481158163384033132&postID=8102289133489793686&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='http://www.blogger.com/share-post.g?blogID=2481158163384033132&postID=8102289133489793686&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a><div class='goog-inline-block dummy-container'><g:plusone source='blogger:blog:plusone' href='http://www.javaadvent.com/2013/12/anatomy-of-java-decompiler.html' size='medium' width='300' annotation='inline'/></div>
</div>
</div>
<div class='post-footer-line post-footer-line-2'></div>
<div class='post-footer-line post-footer-line-3'></div>
</div>
</div>
<div class='comments' id='comments'>
<a name='comments'></a>
<h4>No comments:</h4>
<div id='Blog1_comments-block-wrapper'>
<dl class='avatar-comment-indent' id='comments-block'>
</dl>
</div>
<p class='comment-footer'>
<div class='comment-form'>
<a name='comment-form'></a>
<h4 id='comment-post-message'>Post a Comment</h4>
<p>
</p>
<a href='https://www.blogger.com/comment-iframe.g?blogID=2481158163384033132&postID=8102289133489793686' id='comment-editor-src'></a>
<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' frameborder='0' height='410' id='comment-editor' name='comment-editor' src='' width='100%'></iframe>
<script type="text/javascript" src="https://www.blogger.com/static/v1/jsbin/2290467252-comment_from_post_iframe.js"></script>
<script type='text/javascript'>
      BLOG_CMT_createIframe('https://www.blogger.com/rpc_relay.html');
    </script>
</div>
</p>
<div id='backlinks-container'>
<div id='Blog1_backlinks-container'>
</div>
</div>
</div>
</div>

        </div></div>
      
<!-- google_ad_section_end -->
</div>
<div class='blog-pager' id='blog-pager'>
<span id='blog-pager-newer-link'>
<a class='blog-pager-newer-link' href='http://www.javaadvent.com/2013/12/performance-tuning-measure-dont-guess.html' id='Blog1_blog-pager-newer-link' title='Newer Post'>Newer Post</a>
</span>
<span id='blog-pager-older-link'>
<a class='blog-pager-older-link' href='http://www.javaadvent.com/2013/12/applying-forkjoin-from-optimal-to-fast.html' id='Blog1_blog-pager-older-link' title='Older Post'>Older Post</a>
</span>
<a class='home-link' href='http://www.javaadvent.com/'>Home</a>
</div>
<div class='clear'></div>
<div class='post-feeds'>
<div class='feed-links'>
Subscribe to:
<a class='feed-link' href='http://www.javaadvent.com/feeds/8102289133489793686/comments/default' target='_blank' type='application/atom+xml'>Post Comments (Atom)</a>
</div>
</div>
<script type="text/javascript">window.___gcfg = {'lang': 'en'};</script>
</div></div>
</div>
</div>
<div class='column-left-outer'>
<div class='column-left-inner'>
<aside>
</aside>
</div>
</div>
<div class='column-right-outer'>
<div class='column-right-inner'>
<aside>
</aside>
</div>
</div>
</div>
<div style='clear: both'></div>
<!-- columns -->
</div>
<!-- main -->
</div>
</div>
<div class='main-cap-bottom cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
<footer>
<div class='footer-outer'>
<div class='footer-cap-top cap-top'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
<div class='fauxborder-left footer-fauxborder-left'>
<div class='fauxborder-right footer-fauxborder-right'></div>
<div class='region-inner footer-inner'>
<div class='foot section' id='footer-1'></div>
<table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'>
<tbody>
<tr>
<td class='first columns-cell'>
<div class='foot section' id='footer-2-1'></div>
</td>
<td class='columns-cell'>
<div class='foot section' id='footer-2-2'></div>
</td>
</tr>
</tbody>
</table>
<!-- outside of the include in order to lock Attribution widget -->
<div class='foot section' id='footer-3'><div class='widget Attribution' id='Attribution1'>
<div class='widget-content' style='text-align: center;'>
Simple template. Template images by <a href='http://www.istockphoto.com/googleimages.php?id=11394138&amp;platform=blogger&langregion=en' target='_blank'>luoman</a>. Powered by <a href='http://www.blogger.com' target='_blank'>Blogger</a>.
</div>
<div class='clear'></div>
<span class='widget-item-control'>
<span class='item-control blog-admin'>
<a class='quickedit' href='//www.blogger.com/rearrange?blogID=2481158163384033132&widgetType=Attribution&widgetId=Attribution1&action=editWidget&sectionId=footer-3' onclick='return _WidgetManager._PopupConfig(document.getElementById("Attribution1"));' target='configAttribution1' title='Edit'>
<img alt='' height='18' src='http://img1.blogblog.com/img/icon18_wrench_allbkg.png' width='18'/>
</a>
</span>
</span>
<div class='clear'></div>
</div></div>
</div>
</div>
<div class='footer-cap-bottom cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
</footer>
<!-- content -->
</div>
</div>
<div class='content-cap-bottom cap-bottom'>
<div class='cap-left'></div>
<div class='cap-right'></div>
</div>
</div>
</div>
<script type='text/javascript'>
    window.setTimeout(function() {
        document.body.className = document.body.className.replace('loading', '');
      }, 10);
  </script>
<script type='text/javascript'>
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-36561764-1']);
      _gaq.push(['_trackPageview']);
      (function() {
        var ga = document.createElement('script');
        ga.type = 'text/javascript';
        ga.async = true;
        ga.src = (document.location.protocol == 'https:' ?
                  'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(ga, s);
      })();
    </script>
<script src='//hype-free.googlecode.com/svn/trunk/google-code-prettify/prettify.js' type='text/javascript'></script>
<script>prettyPrint();</script>
<script type="text/javascript">
if (window.jstiming) window.jstiming.load.tick('widgetJsBefore');
</script><script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/2350289290-widgets.js"></script>
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<script type='text/javascript'>
if (typeof(BLOG_attachCsiOnload) != 'undefined' && BLOG_attachCsiOnload != null) { window['blogger_templates_experiment_id'] = "templatesV2";window['blogger_blog_id'] = '2481158163384033132';BLOG_attachCsiOnload('item_'); }_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d2481158163384033132','//www.javaadvent.com/2013/12/anatomy-of-java-decompiler.html','2481158163384033132');
_WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '2481158163384033132', 'bloggerUrl': 'http://www.blogger.com', 'title': 'Java Advent Calendar', 'pageType': 'item', 'postId': '8102289133489793686', 'url': 'http://www.javaadvent.com/2013/12/anatomy-of-java-decompiler.html', 'canonicalUrl': 'http://www.javaadvent.com/2013/12/anatomy-of-java-decompiler.html', 'canonicalHomepageUrl': 'http://www.javaadvent.com/', 'homepageUrl': 'http://www.javaadvent.com/', 'blogspotFaviconUrl': 'http://www.javaadvent.com/favicon.ico', 'enabledCommentProfileImages': true, 'adultContent': false, 'disableAdSenseWidget': false, 'analyticsAccountNumber': 'UA-36561764-1', 'searchLabel': '', 'searchQuery': '', 'pageName': 'Anatomy of a Java Decompiler', 'pageTitle': 'Java Advent Calendar: Anatomy of a Java Decompiler', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'languageDirection': 'ltr', 'feedLinks': '\74link rel\75\42alternate\42 type\75\42application/atom+xml\42 title\75\42Java Advent Calendar - Atom\42 href\75\42http://www.javaadvent.com/feeds/posts/default\42 /\76\n\74link rel\75\42alternate\42 type\75\42application/rss+xml\42 title\75\42Java Advent Calendar - RSS\42 href\75\42http://www.javaadvent.com/feeds/posts/default?alt\75rss\42 /\76\n\74link rel\75\42service.post\42 type\75\42application/atom+xml\42 title\75\42Java Advent Calendar - Atom\42 href\75\42http://www.blogger.com/feeds/2481158163384033132/posts/default\42 /\76\n\n\74link rel\75\42alternate\42 type\75\42application/atom+xml\42 title\75\42Java Advent Calendar - Atom\42 href\75\42http://www.javaadvent.com/feeds/8102289133489793686/comments/default\42 /\76\n', 'meTag': '', 'openIdOpTag': '', 'postImageThumbnailUrl': 'http://3.bp.blogspot.com/-EhdcJg9B53U/Up9ExK_sHHI/AAAAAAAAAYY/1svdXdlriXc/s72-c/fn.png', 'postImageUrl': 'https://upload.wikimedia.org/wikipedia/commons/2/26/Simplified_Control_Flowgraphs.jpg', 'latencyHeadScript': '\74script type\75\42text/javascript\42\76(function() { var b\75window,f\75\42chrome\42,g\75\42tick\42,k\75\42jstiming\42;(function(){function d(a){this.t\75{};this.tick\75function(a,d,c){var e\75void 0!\75c?c:(new Date).getTime();this.t[a]\75[e,d];if(void 0\75\75c)try{b.console.timeStamp(\42CSI/\42+a)}catch(h){}};this[g](\42start\42,null,a)}var a;b.performance\46\46(a\75b.performance.timing);var n\75a?new d(a.responseStart):new d;b.jstiming\75{Timer:d,load:n};if(a){var c\75a.navigationStart,h\75a.responseStart;0\74c\46\46h\76\75c\46\46(b[k].srt\75h-c)}if(a){var e\75b[k].load;0\74c\46\46h\76\75c\46\46(e[g](\42_wtsrt\42,void 0,c),e[g](\42wtsrt_\42,\42_wtsrt\42,h),e[g](\42tbsd_\42,\42wtsrt_\42))}try{a\75null,\nb[f]\46\46b[f].csi\46\46(a\75Math.floor(b[f].csi().pageT),e\46\0460\74c\46\46(e[g](\42_tbnd\42,void 0,b[f].csi().startE),e[g](\42tbnd_\42,\42_tbnd\42,c))),null\75\75a\46\46b.gtbExternal\46\46(a\75b.gtbExternal.pageT()),null\75\75a\46\46b.external\46\46(a\75b.external.pageT,e\46\0460\74c\46\46(e[g](\42_tbnd\42,void 0,b.external.startE),e[g](\42tbnd_\42,\42_tbnd\42,c))),a\46\46(b[k].pt\75a)}catch(p){}})();b.tickAboveFold\75function(d){var a\0750;if(d.offsetParent){do a+\75d.offsetTop;while(d\75d.offsetParent)}d\75a;750\76\75d\46\46b[k].load[g](\42aft\42)};var l\75!1;function m(){l||(l\75!0,b[k].load[g](\42firstScrollTime\42))}b.addEventListener?b.addEventListener(\42scroll\42,m,!1):b.attachEvent(\42onscroll\42,m);\n })();\74/script\076', 'mobileHeadScript': '', 'ieCssRetrofitLinks': '\74!--[if IE]\76\74script type\75\42text/javascript\42 src\75\42https://www.blogger.com/static/v1/jsbin/1969951888-ieretrofit.js\42\76\74/script\76\n\74![endif]--\076', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/76f25a6f2e06af76', 'plusOneApiSrc': 'https://apis.google.com/js/plusone.js', 'sf': 'n', 'tf': ''}}, {'name': 'skin', 'data': {'vars': {'content_padding': '10px', 'paging_background': 'transparent none no-repeat scroll top center', 'image_border_small_size': '2px', 'body_background_gradient_cap': 'none', 'tabs_selected_background_color': '#fcffee', 'body_rule_color': '#eeeddd', 'header_shadow_spread': '3px', 'header_shadow_offset_left': '1px', 'header_padding': '30px', 'link_visited_color': '#888888', 'mobile_background_size': 'auto', 'post_title_font': 'normal normal 24px Georgia, Utopia, \47Palatino Linotype\47, Palatino, serif', 'tabs_text_color': '#999977', 'date_header_margin': 'inherit', 'header_background_gradient': 'url(//www.blogblog.com/1kt/simple/gradients_light.png)', 'header_bottom_border_size': '0', 'content_shadow_spread_webkit': '5px', 'header_shadow_offset_top': '2px', 'mobile_button_color': '#ffffff', 'widget_title_font': 'normal bold 12px Georgia, Utopia, \47Palatino Linotype\47, Palatino, serif', 'main_section_margin': '15px', 'body_background': '#513831 url(//themes.googleusercontent.com/image?id\0751KH22PlFqsiVYxboQNAoJjYmRbw5M4REHmdJbHT5M2x9zVMGrCqwSjZvaQW_A10KPc6Il) repeat scroll top center /* Credit: luoman (http://www.istockphoto.com/googleimages.php?id\07511394138\46amp;platform\75blogger) */', 'keycolor': '#afcc66', 'content_shadow_spread': '40px', 'image_background_color': '#ffffff', 'header_font': 'normal normal 48px Georgia, Utopia, \47Palatino Linotype\47, Palatino, serif', 'header_background_color': '#afcc66', 'main_border_width': '0', 'main_padding': '15px', 'tabs_border_color': '#eeeddd', 'image_text_color': '#222222', 'description_text_size': '140%', 'post_footer_background_color': '#eaeedd', 'body_background_gradient_tile': 'none', 'page_width': 'auto', 'tabs_background_gradient': 'none', 'mobile_background_overlay': 'transparent none repeat scroll top left', 'main_padding_bottom': '30px', 'tabs_background_color': '#fcffee', 'image_border_large_size': '5px', 'post_margin_bottom': '25px', 'body_background_override': '', 'tabs_margin_side': '30px', 'link_hover_color': '#ff9800', 'description_text_color': '#ffffff', 'body_text_color': '#222222', 'content_padding_horizontal': '10px', 'endSide': 'right', 'page_width_selector': '.region-inner', 'date_header_padding': 'inherit', 'post_footer_text_color': '#5e6655', 'startSide': 'left', 'date_header_color': '#222222', 'tabs_font': 'normal normal 16px Georgia, Utopia, \47Palatino Linotype\47, Palatino, serif', 'post_footer_border_color': '#eeeeee', 'body_font': 'normal normal 16px Verdana, Geneva, sans-serif', 'footer_bevel': '0', 'tabs_bevel_border_width': '1px', 'date_header_background_color': 'transparent', 'content_shadow_spread_ie': '10px', 'widget_title_text_color': '#000000', 'header_border_horizontalsize': '0', 'image_border_color': '#eeeeee', 'tabs_border_width': '1px', 'content_background_color': '#fcffee', 'link_color': '#997f00', 'header_text_color': '#ffffff', 'date_header_letterspacing': 'inherit', 'tabs_margin_top': '0', 'main_padding_top': '30px', 'header_border_size': '0', 'tabs_selected_text_color': '#000000', 'content_background_color_selector': '.content-inner', 'body_background_color': '#514831', 'widget_alternate_text_color': '#999999'}, 'override': '/* ---------------- */\npre.prettyprint {\n	display: block;\n	overflow: auto;\n	width: auto;\n	max-height: 700px;\n	white-space: pre;\n	word-wrap: normal;\n	padding: 10px;\n}\ncode.prettyprint {\n	display: block;\n	overflow: auto;\n	width: auto;\n	max-height: 700px;\n	white-space: pre;\n	word-wrap: normal;\n	padding: 10px;\n}'}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\75classic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\75flipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\75magazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\75mosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\75sidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\75snapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\75timeslide'}}}]);
_WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', null, document.getElementById('Navbar1'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', null, document.getElementById('Header1'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML1', 'crosscol', null, document.getElementById('HTML1'), {}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', null, document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/2841940317-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/2392111094-lightbox_bundle.css'}, 'displayModeFull'));
_WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', null, document.getElementById('Attribution1'), {'attribution': 'Simple template. Template images by \74a href\75\47http://www.istockphoto.com/googleimages.php?id\07511394138\46amp;platform\75blogger\46langregion\75en\47 target\75\47_blank\47\76luoman\74/a\76. Powered by \74a href\75\47http://www.blogger.com\47 target\75\47_blank\47\76Blogger\74/a\76.'}, 'displayModeFull'));
</script>
</body>
</html>